let currentTransport = null
let onCloseCb = [], onCb = new Map()
const WebSocket = window.WebSocket

function log(...data) {
    console.log(data)
}

function OnClose(f) {
    onCloseCb = onCloseCb.concat(f)
}

function On(header, f) {
    let cbs = []
    if (onCb.has(header)) {
        cbs = onCb.get(header)
    }
    cbs = cbs.concat(f)
    onCb.set(header, cbs)
}

function fireOnClose(...data) {
    for (let f of onCloseCb) {
        f(data)
    }
}

function fireOn(header, body) {
    if (onCb.has(header)) {
        for (let f of onCb.get(header)) {
            f(header, body)
        }
    }
    if (onCb.has("*")) {
        for (let f of onCb.get("*")) {
            f(header, body)
        }
    }

}

// 连接服务器
async function Connect(url) {
    try {
        currentTransport = new WebSocket(url)
        await currentTransport.ready
        currentTransport.onerror = function (e) {
            log("连接异常", e)
        }
        currentTransport.onmessage = function (e) {
            let fileReader = new FileReader()
            fileReader.readAsArrayBuffer(e.data)
            fileReader.onload = () => {
                let buf = new Uint8Array(fileReader.result)
                if (buf.length > 8) {
                    // 读取长度信息
                    let lenHeader = bytesToInt(buf.slice(0, 4))
                    let lenBody = bytesToInt(buf.slice(4, 8))
                    buf = buf.slice(8)
                    let header, body
                    let decoder = new TextDecoder('utf-8')
                    // 读取header
                    header = decoder.decode(buf.slice(0, lenHeader))
                    buf = buf.slice(lenHeader)
                    // 读取body
                    body = decoder.decode(buf.slice(0, lenBody))
                    // 单次读取完毕
                    fireOn(header, body)
                }
            }
        }
    } catch (e) {
        currentTransport = null
        fireOnClose(e)
        return
    }

    currentTransport.onclose = function (e) {
        fireOnClose(e)
        currentTransport = null
    }
}

async function Emit(header, body) {
    if (null != currentTransport) {
        let encoder = new TextEncoder("utf-8");
        try {
            header = encoder.encode(header)
            body = encoder.encode(body)
            let buf = new Uint8Array(0)
            buf = concat(buf, intToBytes(header.length))
            buf = concat(buf, intToBytes(body.length))
            buf = concat(buf, header)
            buf = concat(buf, body)
            currentTransport.send(buf)
        } catch (e) {
            log("发送数据异常", e)
        }
    }
}

function bytesToInt(raw) {
    return (raw[0] & 0xff) << 24 | (raw[1] & 0xff) << 16 | (raw[2] & 0xff) << 8 | (raw[3]) & 0xff
}

function intToBytes(raw) {
    let result = new Uint8Array(4)
    result[0] = (raw >> 24) & 0xff
    result[1] = (raw >> 16) & 0xff
    result[2] = (raw >> 8) & 0xff
    result[3] = raw & 0xff
    return result
}

function concat(a, b) {
    return Uint8Array.from(Array.from(a).concat(Array.from(b)))
}